package org.ice4apps.talk.callManager;

import java.util.*;

import javax.servlet.sip.SipServletRequest;

import org.ice4apps.util.IceLog;
import org.ice4apps.talk.entity.MessageType;
import org.ice4apps.talk.entity.User;
import org.ice4apps.talk.entity.UserSessionMessage;


/**
 * @author biju
 * This router message will let the different elements to post the message to the 
 * User Session Manager
 */

public class UserSessionMessageRouter extends Thread {
	private static UserSessionMessageRouter userSessionMessageRouter = null;
	private Queue<UserSessionMessage> queue = null;
	private HashMap<String, UserSessionManager> userSessionMap;
	private boolean run = false;
	
	public static UserSessionMessageRouter instantiate() {
		if(userSessionMessageRouter == null) {
			userSessionMessageRouter = new UserSessionMessageRouter();
			userSessionMessageRouter.start();
		}
		return userSessionMessageRouter;
	}
	
	private UserSessionMessageRouter () {
		queue = new LinkedList<UserSessionMessage>();
		userSessionMap = new HashMap <String, UserSessionManager>();
		run = true;
	}
	
	public void postMessage(UserSessionMessage userSessionMessage) {
		synchronized (this) {
			queue.add(userSessionMessage);
		}
		// TODO: Do this correctly
		//notifyAll ();
	}
	
	public void run () {
		while (run){			
			synchronized (this) {
				IceLog.info(this.getClass(), "Waiting ... ");
				try {
					if (queue.isEmpty())
						wait();					
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			IceLog.info(this.getClass(), "Got notification ...");
			execute();
		}
		IceLog.info(this.getClass(), "current queue size: "+queue.size());
	}
	
	private void execute () {
		UserSessionMessage msg = null;
		synchronized (this) {
			msg = queue.poll();
		}
		String dialedDigits = ((SipServletRequest)msg.getMessage()).getTo().getValue();
		IceLog.info(this.getClass(), "Execute dialedDigits" + dialedDigits);

		handleMessage(msg);		
	}
	
	/*  
	 * This method will find the appropriate User Session Manager and post the message
	 */
	private void handleMessage (UserSessionMessage msg) {
		User user = msg.getUser();
		UserSessionManager userSessionManager = null;
		
		IceLog.info(this.getClass(), "Handle Message");
		if (null == (userSessionManager = userSessionMap.get(user.getId())))
		{
			IceLog.info(this.getClass(), "No user session exist, creating one");
			userSessionManager = new UserSessionManager(user);
			userSessionMap.put(user.getId(), userSessionManager);
		}
		
		if (MessageType.REM_USER == msg.getMessageType()){
			removeSession(msg.getUser().getId());
		}
		
		else {
			userSessionManager.postMessage(msg);
		}
	}
	
	public void removeSession(String userId){
		userSessionMap.remove(userId);
	}

	public synchronized void shutdown () {
		run = false;	
		System.out.println("Shutting ...");
		notifyAll();
	}
	

	
}
